package com.lsh.ofc.worker.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.*;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.service.*;
import com.lsh.ofc.proxy.context.WumartBasicContext;
import com.lsh.ofc.proxy.service.OmsServiceProxy;
import com.lsh.ofc.proxy.service.SupplyInfoServiceProxy;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 创建SO任务
 *
 * @author huangdong
 * @date 16/9/5
 */
@Component
public class OfcSoPushJob extends AbstractOfcTaskJob {

    @Autowired
    private OfcOrderService ofcOrderService;

    @Autowired
    private OfcSoService ofcSoService;

    @Autowired
    private OfcCustomerService ofcCustomerService;

    @Autowired
    private OfcStoCreateService ofcStoCreateService;

    @Autowired
    private SupplyInfoServiceProxy supplyInfoServiceProxy;

    @Autowired
    private OmsServiceProxy omsServiceProxy;

    @Autowired
    private SupplierConfigService ofcSupplierService;


    @Override
    protected OfcTaskType getFetchTaskType() {
        return OfcTaskType.SO_PUSH_DMG;
    }

    @Override
    protected int processTask(OfcTask task) throws BusinessException {
        // DC10 的so  推送物美ofc
        boolean ret;
        try {
            Long soBillCode = task.getRefId();
            String content = task.getContent();
            JSONObject contentJson = null;
            if (!StringUtils.isEmpty(content)) {
                contentJson = JSON.parseObject(content);
            }
            if (null == contentJson) {
                return 0;
            }
//            String code = contentJson.getString("warehouseCode");
            String newOrderCode = contentJson.getString("newOrderCode");

            OfcSoHead filter = new OfcSoHead();
            //1 查询 需要 推送物美的DC10的so单，so单 推送进销存成功
            filter.setSoBillCode(soBillCode + "");
            OfcSoHead ofcSoHead = ofcSoService.findOne(filter, true);

//            String suCode = ofcSoHead.getSupplierCode() + "-" + ofcSoHead.getSupplierId();
            String suGroup = "00" + ofcSoHead.getSupplierGroup();

            OfcSupplier supplier = ofcSupplierService.findSupplier(ofcSoHead.getSupplierId(), ofcSoHead.getSupplierCode(), suGroup, ofcSoHead.getSupplierOrg(), ofcSoHead.getRegionCode());
            if (supplier == null) {
                throw EC.ERROR.exception("OFC供货商信息不存在! code=" + ofcSoHead.getSupplierCode() + ": suGroup =" + suGroup);
            }
            logger.info("ofc supplier is {}", JSON.toJSONString(supplier));

            //2 复制so，修改 fullfillchannnel 为物美ofc  插入数据
            OfcOrderHead targetOfcOrderHead = this.initOfcOrderHead(ofcSoHead, Long.valueOf(newOrderCode),supplier);
//            LSHDC2WumartDC lshdc2WumartDC = LSHDC2WumartDC.getEnumDC(code);
            targetOfcOrderHead.setWarehouseCode(supplier.getWarehouseCode());
            targetOfcOrderHead.setWarehouseName(supplier.getWarehouseName());

//            拆单 在库 直流
            List<OfcSoHead> ofcSoHeadList4add = this.initOfcSoHead(ofcSoHead, targetOfcOrderHead, supplier);
            if (null == ofcSoHeadList4add || ofcSoHeadList4add.size() == 0) {
                logger.info("ofcSoHeadList4add size is 0");
                return 0;
            }
            logger.info("ofcSoHeadList4add size is " + ofcSoHeadList4add.size());
            //插入数据库 订单 so单
            int processFlag = this.ofcStoCreateService.create(targetOfcOrderHead, ofcSoHeadList4add);

            if (processFlag > 0) {
                ret = true;
                this.callback(String.valueOf(soBillCode), targetOfcOrderHead.getOrderCode(), ofcSoHead.getOrderCode());
            } else {
                ret = false;
            }
        } catch (BusinessException e) {
            logger.error("任务处理失败", e);
            ret = false;
        }

        return ret ? 1 : -1;
    }

    /**
     * @param newOrderCode 新订单的订单号  用于查询新的soBillCode
     * @param orderCode    原始订单号 用于更新oms订单的soBillCode
     */
    private void callback(String soBillCode, Long newOrderCode, Long orderCode) {
        try {
            OfcSoHead filter = new OfcSoHead();
            filter.setOrderCode(newOrderCode);
            List<OfcSoHead> soHeadList = ofcSoService.findList(filter, false);

            if (CollectionUtils.isEmpty(soHeadList)) {
                return;
            }

            //调用oms的设置订单so code
            Set<String> set = new HashSet<>(soHeadList.size());
            for (OfcSoHead ofcSoHead : soHeadList) {
                set.add(ofcSoHead.getSoBillCode());
            }

            Map<String, Set<String>> map = Collections.singletonMap(soBillCode, set);
            boolean flag = omsServiceProxy.updateOrderInfoOFC(orderCode, map);
            logger.info("更新OMS，soCode，是否成功 ：" + flag);
        } catch (Exception e) {
            logger.error("回调oms失败", e);
        }
    }

    /**
     * @param ofcSoHead
     * @param newOrderCode
     * @return
     */
    private OfcOrderHead initOfcOrderHead(OfcSoHead ofcSoHead, Long newOrderCode,OfcSupplier supplier) {
        OfcOrderHead orderFilter = new OfcOrderHead();
        orderFilter.setOrderCode(ofcSoHead.getOrderCode());
        OfcOrderHead ofcOrderHead = ofcOrderService.findOne(orderFilter, false);

        JSONObject config = JSON.parseObject(supplier.getConfig());
        Long meipiCode = config.getLong("meipiCode");
        OfcCustomer customerDb = ofcCustomerService.getCustomer(meipiCode,CusType.WG_WM.getValue(),ofcSoHead.getRegionCode());

        ofcOrderHead.setId(null);
        int time = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
        ofcOrderHead.setAddressCode(config.getLong("meipiCode"));
        ofcOrderHead.setAddressInfo(this.initAdressInfo(customerDb).toJSONString());
        ofcOrderHead.setOrderCode(newOrderCode);
        ofcOrderHead.setTotalSkuOrderQty(ofcSoHead.getTotalSkuOrderQty());
        ofcOrderHead.setTotalSkuSupplyQty(BigDecimal.ZERO);
        ofcOrderHead.setTotalSkuDeliverQty(BigDecimal.ZERO);
        ofcOrderHead.setTotalSkuReturnQty(BigDecimal.ZERO);
        ofcOrderHead.setFulfillStatus(FulfillStatus.NEW.getValue());

//        OfcCustomer customer = this.getCustomer(ofcOrderHead);
        Map<String, String> ext = new HashMap<>();
        ext.put(Constants.ORDER_H_MP_CUST_CODE, customerDb.getMpCustCode());
        ext.put(Constants.ORDER_H_TRANS_TIME, String.valueOf(time));
        ext.put(Constants.ORDER_H_SUM_FLAG, SumFlag.SUM.getCode());
        //记录此订单的原订单id
        ext.put("p_order_code", ofcSoHead.getOrderCode() + "");
        ofcOrderHead.setExt(JSON.toJSONString(ext));

        List<OfcSoDetail> ofcSoDetails = ofcSoHead.getDetails();
        List<OfcOrderDetail> ofcOrderDetails = new ArrayList<>();
        for (OfcSoDetail ofcSoDetail : ofcSoDetails) {
            OfcOrderDetail orderDetail = new OfcOrderDetail();

            orderDetail.setExt(ofcSoDetail.getExt());
            orderDetail.setGoodsCode(ofcSoDetail.getGoodsCode());
            orderDetail.setGoodsName(ofcSoDetail.getGoodsName());
            orderDetail.setGoodsAmount(ofcSoDetail.getGoodsAmount());
            orderDetail.setGoodsPrice(ofcSoDetail.getGoodsPrice());
            orderDetail.setGoodsSaleUnit(ofcSoDetail.getGoodsSaleUnit());
            orderDetail.setGoodsQty(ofcSoDetail.getSkuOrderQty().divide(ofcSoDetail.getGoodsSaleUnit(), 4, BigDecimal.ROUND_HALF_DOWN));
            orderDetail.setOrderCode(ofcOrderHead.getOrderCode());
            orderDetail.setSkuCode(ofcSoDetail.getSkuCode());
            orderDetail.setCreateTime(ofcSoDetail.getCreateTime());
            orderDetail.setUpdateTime(ofcSoDetail.getUpdateTime());

            orderDetail.setVenderId(ofcSoDetail.getVenderId());

            ofcOrderDetails.add(orderDetail);
        }

        ofcOrderHead.setDetails(ofcOrderDetails);

        return ofcOrderHead;
    }

    /**
     * @return
     */
    private JSONObject initAdressInfo(OfcCustomer customer) {
        JSONObject addressInfo = new JSONObject();
        //超市名称
        addressInfo.put("market_name", customer.getCustName());
        addressInfo.put("province_name", customer.getProvince());
        addressInfo.put("city_name", customer.getCity());
        addressInfo.put("county_name", customer.getDistrict());
        addressInfo.put("address", customer.getAddress());
        addressInfo.put("contact_name", customer.getContactName());
        addressInfo.put("contact_phone", customer.getContactPhone());
        //坐标
        addressInfo.put("real_position", "{}");
        //大车限行
        addressInfo.put("trans_limit", "0");
        // TODO
        addressInfo.put(Constants.ORDER_PRE_WAREHOUSE_CODE, "0");
        addressInfo.put(Constants.ORDER_PRE_WAREHOUSE_NAME, "");
        addressInfo.put(Constants.ORDER_DELIVERY_WAY, 1);
//        addressInfo.put(Constants.ORDER_IS_IN_DMALL, 0);

        return addressInfo;
    }

    /**
     * @param ofcOrderHead
     * @return
     * @throws BusinessException
     */
    private OfcCustomer getCustomer(OfcOrderHead ofcOrderHead) throws BusinessException {
        //校验并更新用户信息
        OfcCustomer param = new OfcCustomer();
        JSONObject addressInfo = JSON.parseObject(ofcOrderHead.getAddressInfo());
        param.setRegionCode(ofcOrderHead.getRegionCode());
        param.setCustCode(ofcOrderHead.getAddressCode());
        param.setCustName(addressInfo.getString("market_name"));
        param.setProvince(addressInfo.getString("province_name"));
        param.setCity(addressInfo.getString("city_name"));
        param.setDistrict(addressInfo.getString("county_name"));
        param.setAddress(addressInfo.getString("address"));
        param.setContactName(addressInfo.getString("contact_name"));
        param.setContactPhone(addressInfo.getString("contact_phone"));
        param.setLocation(addressInfo.getString("real_position"));
        Integer transLimit = addressInfo.getInteger("trans_limit");
        param.setExt(JSON.toJSONString(Collections.singletonMap(Constants.USER_ADDRESS_TRANS_LIMIT, transLimit)));
        // 猪肉采购客户号类型默认是4，文固采购。
        param.setCusType(CusType.WG_WM.getValue());
        return this.ofcCustomerService.updateCustomer(param);
    }


    private List<OfcSoHead> initOfcSoHead(OfcSoHead ofcSoHead, OfcOrderHead ofcOrderHead, OfcSupplier supplier) {

        List<OfcSoDetail> soDetailList = ofcSoHead.getDetails();
        Set<String> supplyCodes = new HashSet<>();
        for (OfcSoDetail soDetail : soDetailList) {
            supplyCodes.add(soDetail.getSkuSupplyCode());
        }
//        LSHDC2WumartDC lshdc2WumartDC = LSHDC2WumartDC.getEnumDC(ofcSoHead.getSupplierDc());
        // 请求 拆单规则接口<code, lgortType>
        Map<String, Integer> splitDetailMap = supplyInfoServiceProxy.getSupplyInfoByCodes(supplyCodes, supplier.getCode(),ofcSoHead.getVenderId());

        if (null == splitDetailMap || splitDetailMap.isEmpty()) {
            logger.info("物美在库or直流拆单so,请求基础服务返回数据失败！soHead bill code  =" + ofcSoHead.getSoBillCode());
            return Collections.EMPTY_LIST;
        }
        Map<String, OfcSoHead> soHeadMap = new HashMap<>();
        //在库，直流 详情
        for (OfcSoDetail soDetail : soDetailList) {
            Integer lgortType = splitDetailMap.get(soDetail.getSkuSupplyCode());
            if (null == lgortType) {
                logger.info("物美在库or直流拆单so,请求基础服务返回数据！没有在库直流属性 code  =" + soDetail.getSkuSupplyCode());
                return Collections.EMPTY_LIST;
            }

            String soHeadKey = ofcSoHead.getSupplierOrg() + ":" + lgortType;
            OfcSoHead targetSoHead = soHeadMap.get(soHeadKey);
            if (null == targetSoHead) {
                targetSoHead = new OfcSoHead();

                BeanUtils.copyProperties(ofcSoHead, targetSoHead);

                targetSoHead.setId(null);
                targetSoHead.setSoStatus(SoStatus.UNCREATED.getValue());
                targetSoHead.setOrderCode(ofcOrderHead.getOrderCode());
                targetSoHead.setSupplierDc(supplier.getSupplierDc());
                targetSoHead.setAddressCode(ofcOrderHead.getAddressCode());
                targetSoHead.setTotalSkuOrderQty(BigDecimal.ZERO);
                targetSoHead.setTotalSkuSupplyQty(BigDecimal.ZERO);
                targetSoHead.setDetails(new ArrayList<OfcSoDetail>());

                targetSoHead.setWarehouseCode(supplier.getWarehouseCode());
                targetSoHead.setWarehouseName(supplier.getWarehouseName());
                targetSoHead.setSupplierOrg(supplier.getSupplierOrg());
                targetSoHead.setSupplierId(supplier.getSupplierId());
                targetSoHead.setSupplierCode(supplier.getCode());
                targetSoHead.setSupplierGroup(supplier.getSupplierGroup());

                targetSoHead.setFulfillChannel(supplier.getFulfillChannel());
                targetSoHead.setFulfillWms(supplier.getFulfillWms());

                JSONObject soExt = JSON.parseObject(ofcOrderHead.getExt());
                soExt.put(Constants.SO_H_SUPPLIER_CODE, supplier.getCode());
                Integer transTime = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
                soExt.put(Constants.SO_H_TRANS_TIME, transTime.toString());
                soExt.put(WumartBasicContext.CUSTYPE, CusType.WG_WM.getValue());
                soExt.put("p_so_bill_code", ofcSoHead.getSoBillCode());
                soExt.put(Constants.SO_H_LGORT_TYPE, lgortType);
                soExt.put(Constants.ORDER_H_SUM_FLAG, SumFlag.SUM.getCode());

                targetSoHead.setExt(soExt.toJSONString());

                soHeadMap.put(soHeadKey, targetSoHead);
            }

            soDetail.setId(null);
            soDetail.setSoBillCode(null);
            soDetail.setSkuSupplyQty(BigDecimal.ZERO);
            soDetail.setSkuReturnQty(BigDecimal.ZERO);
            targetSoHead.getDetails().add(soDetail);

            targetSoHead.setTotalSkuOrderQty(targetSoHead.getTotalSkuOrderQty().add(soDetail.getSkuOrderQty()));
        }

        for (OfcSoHead so : soHeadMap.values()) {
            int i = 0;
            for (OfcSoDetail detail : so.getDetails()) {
                detail.setItemNo((++i) * 10);
            }
        }

        return new ArrayList<>(soHeadMap.values());
    }


    @Override
    protected boolean filterFlag(OfcTask task) {

        return false;
    }

    @Override
    protected List<OfcTask> fetchTasks(OfcTaskType type, Set<OfcTaskStatus> statuses, int shardingCount, List<Integer> shardingItems, int fetchSize) {
        return super.defaultFetchTasks(type, statuses, shardingCount, shardingItems, fetchSize);
    }

}
